//@author A0083782W
#include "stdafx.h"
#include "CppUnitTest.h"


using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace TEUnitTest {		
	TEST_CLASS(UnitTest1) {
	public:
		TEST_METHOD(WordList1) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			WordList newAnalyser;
			newAnalyser.setMessage ("21/9/2014 9pm");
			newAnalyser.solveAll();
			Time timer1,timer2;
			newAnalyser.getStartEndTimer (timer1,timer2);
			string stringActual = timer1.toTimeString() + " " + timer1.toDateString() + " "
				+ timer1.toDayOfWeekString();
			string stringExpected = "21:00 21/9/14 Sunday";
			Assert::AreEqual(stringExpected, stringActual);
		}

		TEST_METHOD(WordList2) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			WordList newAnalyser;
			newAnalyser.setMessage ("21/9/2014 9pm to 11pm");
			newAnalyser.solveAll();
			Time timer1,timer2;
			newAnalyser.getStartEndTimer (timer1,timer2);
			string stringActual1 = timer1.toTimeString() + " " + timer1.toDateString() + " "
				+ timer1.toDayOfWeekString();
			string stringActual2 =  timer2.toTimeString() + " " + timer2.toDateString() + " "
				+ timer2.toDayOfWeekString();
			string stringActual = stringActual1 + " " + stringActual2;
			string stringExpected = "21:00 21/9/14 Sunday 23:00 21/9/14 Sunday";
			Assert::AreEqual(stringExpected, stringActual);
		}

		TEST_METHOD (WordList3) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			WordList newAnalyser;
			newAnalyser.setMessage ("21/9/2014 9pm to 23/9/2014 11pm");
			newAnalyser.solveAll();
			Time timer1,timer2;
			newAnalyser.getStartEndTimer (timer1,timer2);
			string stringActual1 = timer1.toTimeString() + " " + timer1.toDateString() + " "
				+ timer1.toDayOfWeekString();
			string stringActual2 =  timer2.toTimeString() + " " + timer2.toDateString() + " "
				+ timer2.toDayOfWeekString();
			string stringActual = stringActual1 + " " + stringActual2;
			string stringExpected = "21:00 21/9/14 Sunday 23:00 23/9/14 Tuesday";
			Assert::AreEqual(stringExpected, stringActual);
		}

		TEST_METHOD (WordList4) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			WordList newAnalyser;
			newAnalyser.setMessage ("every 2 days");
			newAnalyser.solveAll();
			REPEAT_RULE testRepeatRule;
			testRepeatRule = newAnalyser.getRepeatRule();
			string stringActual = to_string((int)testRepeatRule.frequency);
			stringActual += " ";
			stringActual += to_string((int)testRepeatRule.period);
			stringActual += " ";
			stringActual += to_string((int)testRepeatRule.startOfWeek);
			string stringExpected = "1 2 7";
			Assert::AreEqual(stringExpected, stringActual);
		}

		TEST_METHOD (WordList5) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			WordList newAnalyser;
			newAnalyser.setMessage ("every Sunday");
			newAnalyser.solveAll();
			REPEAT_RULE testRepeatRule;
			testRepeatRule = newAnalyser.getRepeatRule();
			string stringActual = to_string((int)testRepeatRule.frequency);
			stringActual += " ";
			stringActual += to_string((int)testRepeatRule.period);
			stringActual += " ";
			stringActual += to_string((int)testRepeatRule.startOfWeek);
			string stringExpected = "1 7 0";
			Assert::AreEqual(stringExpected, stringActual);
		}

		TEST_METHOD (WordList6) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			WordList newAnalyser;
			newAnalyser.setMessage ("weekly");
			newAnalyser.solveAll();
			REPEAT_RULE testRepeatRule;
			testRepeatRule = newAnalyser.getRepeatRule();
			string stringActual = to_string((int)testRepeatRule.frequency);
			stringActual += " ";
			stringActual += to_string((int)testRepeatRule.period);
			stringActual += " ";
			stringActual += to_string((int)testRepeatRule.startOfWeek);
			string stringExpected = "1 7 7";
			Assert::AreEqual(stringExpected, stringActual);
		}

		TEST_METHOD (WordList7) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			WordList newAnalyser;
			newAnalyser.setMessage ("21/9/2014 9pm");
			Time timer1,timer2;
			newAnalyser.getStartEndTimer (timer1,timer2);
			string stringActual = timer1.toTimeString() + " " + timer1.toDateString() + " "
				+ timer1.toDayOfWeekString();
			string stringExpected = "00:00 0/0/0 ";
			Assert::AreEqual(stringExpected, stringActual);
		}

		TEST_METHOD (Time1) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			Time timer1;
			timer1.setTime (TimeType::DAY, 31);
			timer1.setTime (TimeType::MONTH, 10);
			timer1.setTime (TimeType::YEAR, 13);
			string stringActual = timer1.toDayOfWeekString();
			string stringExpected = "Thursday";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (Time2) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			Time timer1;
			Assert::AreEqual (false, timer1.setTime (TimeType::DAY,32));
		}

		
		TEST_METHOD (Time3) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			Time timer1;
			timer1.setTime (TimeType::DAY,31);
			timer1.setTime (TimeType::MONTH,9);
			Assert::AreEqual (false, timer1.isLastInputLegal());
		}

		TEST_METHOD (Time4) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			Time timer1;
			timer1.setTime (TimeType::DAY,29);
			timer1.setTime (TimeType::MONTH,2);
			Assert::AreEqual (true, timer1.isLastInputLegal());
		}

		TEST_METHOD (Time5) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			Time timer1;
			timer1.setTime (TimeType::DAY,29);
			timer1.setTime (TimeType::MONTH,2);
			timer1.setTime (TimeType::YEAR,13);
			Assert::AreEqual (false, timer1.isLastInputLegal());
		}

		TEST_METHOD (Time6) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			Time timer1;
			timer1.setTime (TimeType::DAY,28);
			timer1.setTime (TimeType::MONTH,2);
			timer1.setTime (TimeType::YEAR,13);
			timer1++;
			string stringActual = timer1.toDateString() + " "
				+ timer1.toDayOfWeekString();
			string stringExpected = "1/3/13 Friday";
			Assert::AreEqual(stringExpected,stringActual);
		}

		TEST_METHOD (Time7) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			Time timer1;
			timer1.setTime (TimeType::DAY,1);
			timer1.setTime (TimeType::MONTH,3);
			timer1.setTime (TimeType::YEAR,16);
			timer1--;
			string stringActual = timer1.toDateString() + " "
				+ timer1.toDayOfWeekString();
			string stringExpected = "29/2/16 Monday";
			Assert::AreEqual(stringExpected,stringActual);
		}

		TEST_METHOD (Time8) {
			Settings::get().setDateDisplayFormat (DateDisplayFormat::DDMMYY);
			Settings::get().setTimeDisplayFormat (TimeDisplayFormat::TWENTY_FOUR);
			Time timer1;
			timer1.setTime (TimeType::DAY,31);
			timer1.setTime (TimeType::MONTH,12);
			timer1.setTime (TimeType::YEAR,16);
			timer1++;
			string stringActual = timer1.toDateString() + " "
				+ timer1.toDayOfWeekString();
			string stringExpected = "1/1/17 Sunday";
			Assert::AreEqual(stringExpected,stringActual);
		}

		TEST_METHOD (IndexTranslator1) {
			IndexTranslator testTranslator;
			vector<pos_int> arr;
			arr.push_back (5);
			arr.push_back (0);
			arr.push_back (3);
			arr.push_back (1);
			testTranslator.setMapping (arr);
			pos_int act = testTranslator.getStorageIndex (4);
			pos_int exp = 1;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (IndexTranslator2) {
			IndexTranslator testTranslator;
			vector<pos_int> arr;
			arr.push_back (5);
			arr.push_back (0);
			arr.push_back (3);
			arr.push_back (1);
			testTranslator.setMapping (arr);
			int act = testTranslator.getStorageIndex (10);
			int exp = -1;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (IndexTranslator3) {
			IndexTranslator testTranslator;
			vector<pos_int> arr;
			arr.push_back (5);
			arr.push_back (0);
			arr.push_back (3);
			arr.push_back (1);
			testTranslator.setMapping (arr);
			testTranslator.deleteMapping (2);
			pos_int act = testTranslator.getStorageIndex (4);
			pos_int exp = 0;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (IndexTranslator4) {
			IndexTranslator testTranslator;
			vector<pos_int> arr;
			arr.push_back (5);
			arr.push_back (0);
			arr.push_back (3);
			arr.push_back (1);
			testTranslator.setMapping (arr);
			testTranslator.deleteMapping (2);
			testTranslator.deleteMapping (3);
			pos_int act = testTranslator.getStorageIndex (1);
			pos_int exp = 3;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (UserCommand1) {
			UserCommand testCommand;
			testCommand.analyse ("");
			pos_int act = (pos_int) testCommand.getError();
			pos_int exp = (pos_int) IllegalInput::UNKNOW_CHARACTERS;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (UserCommand2) {
			UserCommand testCommand;
			testCommand.analyse ("add a\\a\\a\\a\\a\\a\\a\\a\\a");
			pos_int act = (pos_int) testCommand.getError();
			pos_int exp = (pos_int) IllegalInput::ADD_TOO_MANY_PARAMETERS;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (UserCommand3) {
			UserCommand testCommand;
			testCommand.analyse ("add ");
			pos_int act = (pos_int) testCommand.getError();
			pos_int exp = (pos_int) IllegalInput::ADD_NO_TASK_DESCIPTION;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (UserCommand4) {
			UserCommand testCommand;
			testCommand.analyse ("add ahahaha\\ \\ \\ \\tags tatata haha,haha");
			Event *aEvent = (Event*)testCommand.getInput();
			vector<string> *actTagsPtr = aEvent->getTagPtr();
			string stringActual;
			for (auto i:*actTagsPtr) {
				stringActual += (i + " ");
			}

			string stringExpected = "tags tatata haha,haha ";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (UserCommand5) {
			UserCommand testCommand;
			testCommand.analyse ("add ahahaha\\ \\ \\ \\tags tatata haha,haha");
			Event *aEvent = (Event*)testCommand.getInput();
			vector<string> *actTagsPtr = aEvent->getTagPtr();
			pos_int act = actTagsPtr->size();
			pos_int exp = 3;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (UserCommand6) {
			UserCommand testCommand;
			testCommand.analyse ("delete ");
			pos_int act = (pos_int) testCommand.getError();
			pos_int exp = (pos_int) IllegalInput::DELETE_ILLEGAL_PARAMETER;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (UserCommand7) {
			UserCommand testCommand;
			testCommand.analyse ("delete 1,2,3,4 to 7");
			vector<pos_int> *indexArray = (vector<pos_int>*)testCommand.getInput();
			string stringActual;
			for (auto i:*indexArray) {
				stringActual += (to_string(i) + " ");
			}

			string stringExpected = "1 2 3 4 5 6 7 ";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (UserCommand8) {
			UserCommand testCommand;
			testCommand.analyse ("delete 1to4, 1 to 4");
			vector<pos_int> *indexArray = (vector<pos_int>*)testCommand.getInput();
			string stringActual;
			for (auto i:*indexArray) {
				stringActual += (to_string(i) + " ");
			}

			string stringExpected = "1 2 3 4 1 2 3 4 ";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (UserCommand9) {
			UserCommand testCommand;
			testCommand.analyse ("delete 1~4,5,3-6");
			vector<pos_int> *indexArray = (vector<pos_int>*)testCommand.getInput();
			string stringActual;
			for (auto i:*indexArray) {
				stringActual += (to_string(i) + " ");
			}

			string stringExpected = "1 2 3 4 5 3 4 5 6 ";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (UserCommand10) {
			UserCommand testCommand;
			testCommand.analyse ("delete 1 ~ 4,3 - 6");
			vector<pos_int> *indexArray = (vector<pos_int>*)testCommand.getInput();
			string stringActual;
			for (auto i:*indexArray) {
				stringActual += (to_string(i) + " ");
			}

			string stringExpected = "1 2 3 4 3 4 5 6 ";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (UserCommand11) {
			UserCommand testCommand;
			testCommand.analyse ("undo");
			vector<pos_int>* vectorPos_int = (vector<pos_int>*)testCommand.getInput();
			pos_int exp = (*vectorPos_int)[0];
			pos_int act = 1;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (UserCommand12) {
			UserCommand testCommand;
			testCommand.analyse ("help add");
			OperationType *aType = (OperationType*) testCommand.getInput();
			string stringActual = to_string((int)testCommand.getOperationType());
			stringActual += " ";
			stringActual += to_string((int)*aType);
			string stringExpected = "6 1";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (UserCommand13) {
			UserCommand testCommand;
			testCommand.analyse ("help hahaha");
			OperationType *aType = (OperationType*) testCommand.getInput();
			string stringActual = to_string((int)testCommand.getOperationType());
			stringActual += " ";
			stringActual += to_string((int)*aType);
			string stringExpected = "6 0";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (UserCommand14) {
			UserCommand testCommand;
			testCommand.analyse ("help   ");
			OperationType *aType = (OperationType*) testCommand.getInput();
			string stringActual = to_string((int)testCommand.getOperationType());
			stringActual += " ";
			stringActual += to_string((int)*aType);
			string stringExpected = "6 0";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (TECommon_ignoreCase1) {
			string testStr;
			testStr = "AAdefeAA0123";
			testStr = ignoreCase (testStr);
			string stringExpected = "aadefeaa0123";
			Assert::AreEqual (stringExpected, testStr);
		}

		TEST_METHOD (TECommon_ignoreCase2) {
			string testStr;
			testStr = "AAdefeAA0123";
			ignoreCase (&testStr);
			string stringExpected = "aadefeaa0123";
			Assert::AreEqual (stringExpected, testStr);
		}

		TEST_METHOD (TECommon_ignoreCase3) {
			string testStr;
			testStr = "AAdefeAA0123";
			ignoreCase (testStr);
			string stringExpected = "AAdefeAA0123";
			Assert::AreEqual (stringExpected, testStr);
		}

		TEST_METHOD (TECommon_splitString1) {
			con_chr sepChar[] = {' ', ','};
			const pos_int sepCharSize = 2;
			vector<string> stringList;
			vector<pos_int> numberList;
			string stringExpected;
			string stringActual;

			splitString ("ha haha hahaha", sepChar, sepCharSize, stringList, numberList);
			for (auto i:stringList) {
				stringActual += (i + " ");
			}

			stringExpected = "ha haha hahaha ";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (TECommon_splitString2) {
			con_chr sepChar[] = {' ', ','};
			const pos_int sepCharSize = 2;
			vector<string> stringList;
			vector<pos_int> numberList;
			string stringExpected;
			string stringActual;

			pos_int act = splitString ("hahahahahaha", sepChar, sepCharSize, stringList, numberList);
			pos_int exp = 1;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (TECommon_splitString3) {
			con_chr sepChar[] = {' ', ','};
			const pos_int sepCharSize = 2;
			vector<string> stringList;
			vector<pos_int> numberList;
			string stringExpected;
			string stringActual;

			splitString ("", sepChar, sepCharSize, stringList, numberList);
			for (auto i:stringList) {
				stringActual += (i + " ");
			}
			stringActual += to_string(numberList.size());
			stringExpected = "0";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (TECommon_cutWordsFromString1) {
			con_chr sepChar[] = {'|'};
			const pos_int sepCharSize = 1;
			vector<string> stringList;
			string stringExpected;
			string stringActual;

			cutWordsFromString ("", sepChar, sepCharSize, stringList);
			for (auto i:stringList) {
				stringActual += (i + " ");
			}
			stringExpected = "";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (TECommon_cutWordsFromString2) {
			con_chr sepChar[] = {'|'};
			const pos_int sepCharSize = 1;
			vector<string> stringList;
			string stringExpected;
			string stringActual;

			cutWordsFromString (" ", sepChar, sepCharSize, stringList);
			for (auto i:stringList) {
				stringActual += (i + " ");
			}
			stringExpected = "  ";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (TECommon_cutWordsFromString3) {
			con_chr sepChar[] = {'|'};
			const pos_int sepCharSize = 1;
			vector<string> stringList;
			string stringExpected;
			string stringActual;

			cutWordsFromString ("| |", sepChar, sepCharSize, stringList);
			for (auto i:stringList) {
				stringActual += (i + "0");
			}
			stringExpected = "0 00";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (TECommon_cutWordsFromString4) {
			con_chr sepChar[] = {'|'};
			const pos_int sepCharSize = 1;
			vector<string> stringList;
			string stringExpected;
			string stringActual;

			cutWordsFromString (" | |", sepChar, sepCharSize, stringList);
			for (auto i:stringList) {
				stringActual += (i + "0");
			}
			stringExpected = " 0 00";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (TECommon_splitLines) {
			vector<string> result;
			con_chr sepChar[] = {' '};
			const pos_int sepCharSize = 1;
			string stringActual;
			result = splitLines("a apple jumps over the bridge and bite a mosquito", 20, sepChar, sepCharSize);
			for (auto i:result) {
				stringActual += i;
				stringActual += "0";
			}

			string stringExpected = "a apple jumps over 0the bridge and bite 0a mosquito0";
			Assert::AreEqual (stringExpected, stringActual);
		}

		TEST_METHOD (TECommon_isLeapYear1) {
			bool act = isLeapYear (16);
			bool exp = true;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (TECommon_isLeapYear2) {
			bool act = isLeapYear (0);
			bool exp = true;
			Assert::AreEqual (exp, act);
		}

		TEST_METHOD (TECommon_isLeapYear3) {
			bool act = isLeapYear (99);
			bool exp = false;
			Assert::AreEqual (exp, act);
		}
		
		TEST_METHOD (TECommon_getMaxday1) {
			ByteInt act = getMaxDay (0,Month::JANUARY);
			ByteInt exp = 31;
			Assert::AreEqual (exp,act);
		}

		TEST_METHOD (TECommon_getMaxday2) {
			ByteInt act = getMaxDay (0 ,Month::FEBURARY);
			ByteInt exp = 29;
			Assert::AreEqual (exp,act);
		}

		TEST_METHOD (TECommon_getMaxday3) {
			ByteInt act = getMaxDay (3 ,Month::FEBURARY);
			ByteInt exp = 28;
			Assert::AreEqual (exp,act);
		}
	};
}